using System;
using System.Collections;
using System.Text.RegularExpressions;
using System.Text;

namespace SharpVectors.Dom.Svg
{
  /// <summary>
  /// This class defines a list of SvgPoint objects. 
  /// </summary>
  /// <developer>niklas@protocol7.com</developer>
  /// <developer>kevin@kevlindev.com</developer>
  /// <completed>100</completed>
  public class SvgPointList : SvgList, ISvgPointList
  {
    #region Constructors
    public SvgPointList()
    {

    }

    public SvgPointList(string listString)
    {
      this.FromString(listString);
    }
    #endregion

    #region ISvgStringList Interface
    public ISvgPoint Initialize(ISvgPoint newItem)
    {
      return (SvgPoint) base.Initialize(newItem);
    }

    public new ISvgPoint GetItem(uint index)
    {
      return (SvgPoint) base.GetItem(index);
    }

    public ISvgPoint InsertItemBefore(ISvgPoint newItem, uint index)
    {
      return (SvgPoint) base.InsertItemBefore(newItem, index);
    }

    public ISvgPoint ReplaceItem(ISvgPoint newItem, uint index)
    {
      return (SvgPoint) base.ReplaceItem(newItem, index);
    }

    public new ISvgPoint RemoveItem(uint index)
    {
      return (SvgPoint) base.RemoveItem(index);
    }

    public ISvgPoint AppendItem(ISvgPoint newItem)
    {
      return (SvgPoint) base.AppendItem(newItem);
    }
    #endregion

    public void FromString(string listString)
    {
      // remove existing list items
      Clear();

      if ( listString != null )
      {
        int len = listString.Length; // temp

        if ( len > 0 )
        {
          int p = 0; // pos
          char c; // temp
          int sNum = -1; // start of the number
          int eNum = -1; // end of the number
          bool seenComma = false; // to handle 123,,123
          int tempSNum = -1; // start of the number (held in temp until two numbers are found)
          int tempENum = -1; // end of the number (held in temp until two numbers are found)

          // This used to be a regex-- it is *much* faster this way
          while (p<len)
          {
            // Get the char in a temp
            c = listString[p];

            // TODO: worry about NEL?
            if ((c=='\t') || (c=='\r') || (c=='\n') || (c==0x20) || (c==','))
            {
              // Special handling for two commas
              if (c==',') 
              {
                if (seenComma && sNum < 0)
                  throw new SvgException(SvgExceptionType.SvgInvalidValueErr);
                seenComma = true;
              }

              // Are we in a number?
              if (sNum >= 0) 
              {
                // The end of the number is the previous char
                eNum = p-1;

                // Is this the x or y?
                if (tempSNum == -1) 
                {
                  // must be the x, hang onto it for a second
                  tempSNum = sNum;
                  tempENum = eNum;
                }
                else 
                {
                  // must be the y, use temp as x and append the item
                  AppendItem( new SvgPoint((double)SvgNumber.ParseToFloat(listString.Substring(tempSNum, (tempENum-tempSNum)+1)), 
                    (double)SvgNumber.ParseToFloat(listString.Substring(sNum, (eNum-sNum)+1))) );
                  tempSNum = -1;
                  tempENum = -1;
                }

                // Reset
                sNum = -1;
                eNum = -1;
                seenComma = false;
              }
            } 
            else if (sNum == -1)
              sNum = p;
            // OPTIMIZE: Right here we could check for [Ee] to save some time in IndexOfAny later
                  
            // Move to next char
            p++;
          }

          // We need to handle the end of the buffer as a delimiter
          if (sNum >= 0) 
          {
            if (tempSNum == -1)
              throw new SvgException(SvgExceptionType.SvgInvalidValueErr);

            // The end of the number is the previous char
            eNum = p-1;
            // must be the y, use temp as x and append the item
            AppendItem( new SvgPoint((double)SvgNumber.ParseToFloat(listString.Substring(tempSNum, (tempENum-tempSNum)+1)), 
              (double)SvgNumber.ParseToFloat(listString.Substring(sNum, (eNum-sNum)+1))) );
          }
          else if (tempSNum != -1) 
          {
            throw new SvgException(SvgExceptionType.SvgInvalidValueErr);
          }
        }                  
      }
    }
  }
}
